<html>
<head><meta charset="utf-8"><title>Lifetimes and enum destructuring · t-compiler/help · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/index.html">t-compiler/help</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html">Lifetimes and enum destructuring</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="244281588"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244281588" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> John Baublitz <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244281588">(Jun 29 2021 at 13:38)</a>:</h4>
<p>hi everyone! I'm a little bit surprised about the behavior of the compiler in the following code snippet. I'd like to understand a little bit better why I'm seeing this. the following code snippet:</p>
<div class="codehilite"><pre><span></span><code>struct DataStructure {
    inner: u16,
    flag: bool,
}

impl DataStructure {
    fn new(inner: u16) -&gt; Self {
        DataStructure {
            inner,
            flag: false,
        }
    }

    fn res(&amp;mut self, error: bool) -&gt; Result&lt;&amp;mut u16, String&gt; {
        fn res_inner(s: &amp;mut DataStructure, error: bool) -&gt; Result&lt;&amp;mut u16, String&gt; {
            if error {
                Err(&quot;Returned error&quot;.to_string())
            } else {
                Ok(&amp;mut s.inner)
            }
        }

        match res_inner(self, error) {
            Ok(r) =&gt; Ok(r),
            Err(e) =&gt; {
                self.flag = true;
                Err(e)
            }
        }
    }
}
</code></pre></div>
<p>fails with the error:</p>
<div class="codehilite"><pre><span></span><code>   Compiling playground v0.0.1 (/playground)
error[E0506]: cannot assign to `self.flag` because it is borrowed
  --&gt; src/lib.rs:26:17
   |
14 |     fn res(&amp;mut self, error: bool) -&gt; Result&lt;&amp;mut u16, String&gt; {
   |            - let&#39;s call the lifetime of this reference `&#39;1`
...
23 |         match res_inner(self, error) {
   |                         ---- borrow of `self.flag` occurs here
24 |             Ok(r) =&gt; Ok(r),
   |                      ----- returning this value requires that `*self` is borrowed for `&#39;1`
25 |             Err(e) =&gt; {
26 |                 self.flag = true;
   |                 ^^^^^^^^^^^^^^^^ assignment to borrowed `self.flag` occurs here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0506`.
error: could not compile `playground`

To learn more, run the command again with --verbose.
</code></pre></div>
<p>the reason that this is surprising to me is that the lifetime is only specified in the <code>Ok</code> variant, not the <code>Err</code> variant. Rust does not seem to be able to determine that the borrow is no longer active by matching on the <code>Err</code> variant most likely due to the wrapped method.</p>
<p>this example is definitely contrived but it is the same pattern that I need to apply for some autogenerated code that is failing to compile when the return type is a reference borrowed from <code>self</code>. is there a way around this? I've even tried destructuring the <code>Err</code> type and returning early on the <code>Ok</code> variant to try to make the compiler understand that this borrow is not active in the <code>Err</code> code path, but even that doesn't seem to work.</p>



<a name="244295018"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244295018" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244295018">(Jun 29 2021 at 14:58)</a>:</h4>
<p>I believe polonius will fix this when/if it lands.</p>



<a name="244298175"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244298175" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> John Baublitz <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244298175">(Jun 29 2021 at 15:15)</a>:</h4>
<p>I thought that had already landed. was there a separate restructuring of the borrow checker that has already made it in?</p>



<a name="244298475"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244298475" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> John Baublitz <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244298475">(Jun 29 2021 at 15:17)</a>:</h4>
<p>(I'm referring to this blog post: <a href="https://blog.rust-lang.org/2019/11/01/nll-hard-errors.html">https://blog.rust-lang.org/2019/11/01/nll-hard-errors.html</a>)</p>



<a name="244298786"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244298786" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244298786">(Jun 29 2021 at 15:19)</a>:</h4>
<p>There is the old ast borrowck, the current mir borrowck (this is what that post is about) and polonius, which is a reformulation of the borrow checking logic in datalog: <a href="https://smallcultfollowing.com/babysteps/blog/2018/04/27/an-alias-based-formulation-of-the-borrow-checker/">https://smallcultfollowing.com/babysteps/blog/2018/04/27/an-alias-based-formulation-of-the-borrow-checker/</a></p>



<a name="244299257"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244299257" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244299257">(Jun 29 2021 at 15:21)</a>:</h4>
<p>Note that the nll borrowchecker at one point was location sensitive as necessary to accept this code, but it was made location insensitive due to performance issues. Polonius can elegantly represent both options using only like <del>50</del> 200 extra lines of code.</p>



<a name="244299521"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244299521" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244299521">(Jun 29 2021 at 15:23)</a>:</h4>
<p><a href="https://github.com/rust-lang/polonius/blob/master/polonius-engine/src/output/location_insensitive.rs">https://github.com/rust-lang/polonius/blob/master/polonius-engine/src/output/location_insensitive.rs</a> and <a href="https://github.com/rust-lang/polonius/blob/master/polonius-engine/src/output/datafrog_opt.rs">https://github.com/rust-lang/polonius/blob/master/polonius-engine/src/output/datafrog_opt.rs</a></p>



<a name="244300987"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Lifetimes%20and%20enum%20destructuring/near/244300987" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> John Baublitz <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Lifetimes.20and.20enum.20destructuring.html#244300987">(Jun 29 2021 at 15:32)</a>:</h4>
<p>okay! I didn't realize that that blog post was about mir instead of polonius. I saw a talk on polonius so I was under the impression that they were the same.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>